package com.dongzili.demo.common.config.redis;

import com.dongzili.demo.common.utils.ReflectUtils;
import org.springframework.data.redis.core.*;
import org.springframework.util.StringUtils;


import java.util.*;
import java.util.stream.Collectors;

/**
 * redis hash数据操作服务
 * @author dongzili
 * @param <T>
 */
public class RedisHashService<T> {

    /**
     * 获取 Hash 操作对象
      */
    private final HashOperations<String, String, T> hashOps;
    private final Class<T> tClass;
    private final String key;

    public RedisHashService(Class<T> tClass) {
        RedisTemplate<String, T> redisTemplate = RedisTemplateConfig.getRedisTemplate();
        this.hashOps = redisTemplate.opsForHash();
        this.tClass = tClass;
        this.key = "hash-"+tClass.getSimpleName();
    }


    /**
     * 增加或更新数据
     */
    public void addOrUpdate(String hashKey, String field, T value) {
        hashOps.put(hashKey, field, value);
    }
    public void addOrUpdate(T value) {
//        Object id = ReflectUtils.getPrimaryValue(value);
//        if (id == null){
//            throw new RuntimeException("主键不能为空");
//        }
        List<String> indexValues = ReflectUtils.getIndexedData(value);
        hashOps.put(key, String.join(",", Objects.requireNonNull(indexValues)), value);
    }

    public void addOrUpdateBatch(String hashKey, Map<String, T> fieldsAndValues) {
        hashOps.putAll(hashKey, fieldsAndValues);
    }
    public void addOrUpdateBatch(List<T> values) {

        Map<String, T> fieldsAndValues = values.stream().collect(Collectors.toMap(value -> String.join(",", Objects.requireNonNull(ReflectUtils.getIndexedData(value))), value -> value));
        hashOps.putAll(key, fieldsAndValues);
    }

    /**
     * 获取单个字段的值
     * @param hashKey
     * @param field
     * @return
     */
    public T get(String hashKey, String field) {
        return hashOps.get(hashKey, field);
    }

    public T get(String primaryKey) {
        return hashOps.get(key, primaryKey);
    }

    /**
     * 获取整个 Hash 的数据
     * @param hashKey
     * @return
     */
    public Map<String, T> getAll(String hashKey) {
        return hashOps.entries(hashKey);
    }

    /**
     * 删除单个字段
     * @param hashKey
     * @param field
     */
    public void delete(String hashKey, String field) {
        hashOps.delete(hashKey, field);
    }

    public List<T> findByPage(String keyword, int page, int pageSize) {
//        ScanOptions options = ScanOptions.scanOptions()
//                .match(keyword) // 匹配所有字段
//                .count(pageSize) // 每次扫描返回的最大记录数
//                .build();
        ScanOptions options;
        if(StringUtils.hasText(keyword)){
            options = ScanOptions.scanOptions().match(keyword).count(100000000).build();
        }else{
            options = ScanOptions.scanOptions().count(100000000).build();
        }
        int totalRecords = 0;
        List<T> pageData = new ArrayList<>();
        try(Cursor<Map.Entry<String, T>> cursor = hashOps.scan(key, options)){
            while (cursor.hasNext()) {
                Map.Entry<String, T> entry = cursor.next();
                if (totalRecords >= pageSize * (page - 1)) {
                    pageData.add(entry.getValue());
                }
                totalRecords++;
                if (totalRecords >= pageSize * page) {
                    break;
                }
            }
//            System.out.println("CursorId: "+cursor.getCursorId());
        }
        return pageData;
    }










}
